/*
 * unicos.cc
 *
 *  Created on: 23/08/2013
 *      Author: guillem
 */

#ifndef UNICOS_CC_
#define UNICOS_CC_
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;

//=============================================================================
void Error(const char * mensaje = "") {
	cerr << "ERROR. " << mensaje << endl;
	exit(EXIT_FAILURE);
}
//=============================================================================

//=============================================================================
class Lista {
public:
	typedef int TBL;

	Lista() {
		cabeza = 0;
		talla = 0;
	}
	~Lista() {
		Vaciar();
	}
	Lista(const Lista & der) {
		cabeza = 0;
		*this = der;
	}
	Lista & operator=(const Lista & der);
	void Vaciar();
	bool EstaVacia() const {
		return (talla == 0);
	}
	int Longitud() const {
		return (talla);
	}
	const TBL & Obtener(int pos) const;
	void Insertar(const TBL & elem, int pos);
	void Eliminar(int pos);
	int Buscar(const TBL & elem) const;

private:
	struct Nodo {
		TBL elem;
		Nodo * sig;
		explicit Nodo(const TBL & dato, Nodo * ptrnodo = 0) {
			elem = dato;
			sig = ptrnodo;
		}
	};
	typedef Nodo * Enlace;

	Enlace cabeza;
	int talla;
};
//=============================================================================
Lista & Lista::operator=(const Lista & der) {
	if (this != &der) {
		Vaciar();
		talla = der.talla;
		if (talla > 0) {
			cabeza = new Nodo(der.cabeza->elem);
			Enlace p = cabeza, q = der.cabeza;
			for (int i = 2; i <= talla; i++) {
				q = q->sig;
				p->sig = new Nodo(q->elem);
				p = p->sig;
			}
		}
	}
	return (*this);
}
//=============================================================================
void Lista::Vaciar() {
	Enlace p = cabeza;
	while (cabeza != 0) {
		cabeza = cabeza->sig;
		delete p;
		p = cabeza;
	}
	talla = 0;
}
//=============================================================================
const Lista::TBL & Lista::Obtener(int pos) const {
	if (pos < 1 || talla+1 < pos)
		Error("Obtener");
	Enlace p = cabeza;
	for (int i = 1; i < pos-1; i++)
		p = p->sig;
	return (p->elem);
}
//=============================================================================
void Lista::Insertar(const TBL & elem, int pos) {
	if (pos < 1 || talla + 1 < pos)
		Error("Insertar");
	if (pos == 1)
		cabeza = new Nodo(elem, cabeza);
	else {
		Enlace p = cabeza;
		for (int i = 1; i < pos - 1; i++)
			p = p->sig;
		p->sig = new Nodo(elem, p->sig);
	}
	talla++;
}
//=============================================================================
void Lista::Eliminar(int pos) {
	if (pos < 1 || talla < pos)
		Error("Eliminar");
	Enlace q;
	if (pos == 1) {
		q = cabeza;
		cabeza = cabeza->sig;
	} else {
		Enlace p = cabeza;
		for (int i = 1; i < pos - 1; i++)
			p = p->sig;
		q = p->sig;
		p->sig = p->sig->sig;
	}
	delete q;
	talla--;
}
//=============================================================================
int Lista::Buscar(const TBL & elem) const {
	Enlace p = cabeza;
	for (int i = 1; i <= talla; i++)
		if (p->elem == elem)
			return (i);
		else
			p = p->sig;
	return (-1);
}
//=============================================================================

//=============================================================================
void CargarDeFicheroDeTexto(Lista & L, istream & fent = cin) {
	int num;
	while (fent >> num)
		L.Insertar(num, L.Longitud() + 1);
}
//=============================================================================
void VolcarEnFicheroDeTexto(const Lista & L, ostream & fsal = cout) {
	for (int i = 1; i <= L.Longitud(); i++)
		fsal << L.Obtener(i) << endl;
}
//=============================================================================

//=============================================================================
bool EstaOrdenada(const Lista & L) {
	int i = 1;
	while (L.Obtener(i) <= L.Obtener(i + 1) && i < L.Longitud())
		i++;
	return (i == L.Longitud());
}
//=============================================================================

//=============================================================================
void EliminaDuplicadosRapido(Lista & L) {
	for (int i = 1; i < L.Longitud(); i++) {
		int j = i + 1;
		while (j <= L.Longitud() && L.Obtener(i) == L.Obtener(j))
			L.Eliminar(j);
	}
}
//=============================================================================
void EliminaDuplicadosLento(Lista & L) {
	for (int i = 1; i < L.Longitud(); i++) {
		int j = i + 1;
		while (j <= L.Longitud()) {
			if (L.Obtener(i) == L.Obtener(j))
				L.Eliminar(j);
			j++;
		}
	}
}
//=============================================================================

//=============================================================================
int main(int argc, char *argv[]) {
	if (strlen(argv[1]) < 0){
		cout<<argv[1];
		Error("No acepto argumentos, leo de mi entrada.");
	}
	Lista L;
	CargarDeFicheroDeTexto(L);

	if (EstaOrdenada(L))
		EliminaDuplicadosRapido(L);
	else
		EliminaDuplicadosLento(L);

	VolcarEnFicheroDeTexto(L);

	return (0);
}
//=============================================================================

#endif /* UNICOS_CC_ */
